package org.tau.workshop2011.widgets

import scala.collection.mutable.{Map => MutableMap, HashMap => MutableHashMap}
import org.tau.workshop2011.codegen.{DSLProperty, Property}
import org.tau.workshop2011.expressions.{Font, Color}

/* A base class for allowing to connect properties to native values */
abstract class NativePropertyBinder[T](val property: DSLProperty[T]) {
  def get: T
  protected def realSet(newVal: T)
  protected var passFromExternal = true
  protected var passFromNative = property != null && ! property.isReadOnly
  def callOnNativeChange(newVal: T) {
    if (property != null && passFromNative)
      property set newVal
  }

  if (property != null) {
    realSet(property.get)
    property.addChangeListener((_,_,newVal: T) => if (passFromExternal) realSet(newVal))
  }

  def callOnNativeChange() {
    callOnNativeChange(get)
  }

  def disconnectExternalChanges() {
    passFromExternal = false
  }

  def disconnectNativeChanges() {
    passFromNative = false
  }
}


class BaseWidget[T <: javax.swing.JComponent] (widget: T, props: Map[String, Property[_]], width: Option[DSLProperty[Int]], height: Option[DSLProperty[Int]])
  extends NativeWidgetWrapper{

  val realWidget : T = widget;
  val native_props : MutableMap[String,NativePropertyBinder[_]] = new MutableHashMap[String,NativePropertyBinder[_]]

  override def getNativeWidget = realWidget
  override def getWidth = width
  override def getHeight = height

  val enabledBind = new NativePropertyBinder(props.getOrElse("enabled", null).asInstanceOf[DSLProperty[Boolean]]) {
    def get = realWidget.isEnabled

    protected def realSet(newVal: Boolean) { realWidget.setEnabled(newVal) }
  }
  native_props += "enabled" -> enabledBind

  val fgcolorBind = new NativePropertyBinder(props.getOrElse("fgcolor", null).asInstanceOf[DSLProperty[Color]]) {
    def get = Color fromSwing realWidget.getForeground

    protected def realSet(newVal: Color) { realWidget.setForeground(newVal.toJava()) }
  }
  native_props += "fgcolor" -> fgcolorBind

  val bgcolorBind = new NativePropertyBinder(props.getOrElse("bgcolor", null).asInstanceOf[DSLProperty[Color]]) {
    def get = Color fromSwing realWidget.getBackground

    protected def realSet(newVal: Color) { realWidget.setBackground(newVal.toJava()) }
  }
  native_props += "bgcolor" -> bgcolorBind

  val fontBind = new NativePropertyBinder(props.getOrElse("font", null).asInstanceOf[DSLProperty[Font]]) {
    def get = Font fromSwing realWidget.getFont

    protected def realSet(newVal: Font) { realWidget.setFont(newVal.toSwing()) }
  }
  native_props += "font" -> fontBind

  realWidget.setOpaque (true) /* For the background color to catch */

  if (width != None)
    SizingUtils.mutateAllComponentSizes(realWidget, (dim) => new java.awt.Dimension(width.get.get, dim.height))

  if (height != None)
    SizingUtils.mutateAllComponentSizes(realWidget, (dim) => new java.awt.Dimension(dim.width, height.get.get))
}
